package gamelogic

import (
	"math"
	"server_cluster/common/config"
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/mysock"
	"server_cluster/common/protoc/pb"
	"server_cluster/http/pkg/random"
	"server_cluster/logic/sharemem"
	"slices"
	"strconv"
	"strings"
)

func EquipUpgradeReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_EquipUpgradeReq, new(pb.CS_EquipUpgradeReq), buf, user).(*pb.CS_EquipUpgradeReq)
	if !ok {
		return config.PROTO_ERROR
	}

	equip := user.GetEquip4Key(req.EquipKey)
	if equip == nil {
		logger.Error("equip not exist, equipKey: %v, uid: %v", req.EquipKey, user.GetUid())
		return SendMsg(config.SC_EquipUpgradeRsp, &pb.SC_EquipUpgradeRsp{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
	}
	ret := EquipUpgrade(equip, req, user)
	if ret != config.OK {
		logger.Error("equip upgrade fail, equip: %v, uid: %v", equip, user.GetUid())
		return SendMsg(config.SC_EquipUpgradeRsp, &pb.SC_EquipUpgradeRsp{RetCode: int32(ret)}, buf, user)
	}

	SendMsg(config.SC_EquipUpdateNtf, &pb.SC_EquipUpdateNtf{Equip: sharemem.PacketEquip(equip, user)}, buf, user)
	var pbRole *pb.User_Role = nil
	if equip.RoleId != 0 {
		role := user.GetRoleById(equip.RoleId)
		if role == nil {
			logger.Error("role not exist, roleId: %v, uid: %v", equip.RoleId, user.GetUid())
			return SendMsg(config.SC_EquipUpgradeRsp, &pb.SC_EquipUpgradeRsp{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
		}
		pbRole = user.PacketUserRole(role)
	}
	return SendMsg(config.SC_EquipUpgradeRsp, &pb.SC_EquipUpgradeRsp{RetCode: config.OK, Equip: sharemem.PacketEquip(equip, user), Role: pbRole}, buf, user)
}

// func EquipAffixRemakeReq(user *sharemem.User) int16 {
// 	req, ok := user.ParseMsg(config.CS_EquipAffixRemakeReq, new(pb.CS_EquipAffixRemakeReq)).(*pb.CS_EquipAffixRemakeReq)
// 	if !ok {
// 		return config.PROTO_ERROR
// 	}
//
// 	equip, _ := user.EquipMap.Get(req.EquipKey)
// 	if equip == nil {
// 		logger.Error("equip not exist, equipKey: %v, uid: %v", req.EquipKey, user.GetUid())
// 		return user.SendMsg(config.SC_EquipAffixRemakeRsp, &pb.SC_EquipAffixRemakeRsp{RetCode: config.OBJECT_NOT_FOUND})
// 	}
// 	if !req.ReplaceConfirm {
// 		ret := user.EquipAffixRemake(equip, req)
// 		if ret != config.OK {
// 			logger.Error("equip affix remake fail, equip: %v, uid: %v", equip, user.GetUid())
// 			return user.SendMsg(config.SC_EquipAffixRemakeRsp, &pb.SC_EquipAffixRemakeRsp{RetCode: int32(ret)})
// 		}
// 	} else {
// 		user.EquipAffixReplace(equip)
// 	}
//
// 	user.SendMsg(config.SC_EquipUpdateNtf, &pb.SC_EquipUpdateNtf{Equip: user.PacketEquip(equip)})
// 	var pbRole *pb.User_Role = nil
// 	if equip.RoleId != 0 {
// 		role, _ := user.RoleMap.Get(equip.RoleId)
// 		if role == nil {
// 			logger.Error("role not exist, roleId: %v, uid: %v", equip.RoleId, user.GetUid())
// 			return user.SendMsg(config.SC_EquipAffixRemakeRsp, &pb.SC_EquipAffixRemakeRsp{RetCode: config.OBJECT_NOT_FOUND})
// 		}
// 		pbRole = user.PacketUserRole(role)
// 	}
// 	return user.SendMsg(config.SC_EquipAffixRemakeRsp, &pb.SC_EquipAffixRemakeRsp{RetCode: config.OK, Equip: user.PacketEquip(equip), Role: pbRole, ReplaceConfirm: req.ReplaceConfirm})
// }

func EquipWearReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_EquipWearReq, new(pb.CS_EquipWearReq), buf, user).(*pb.CS_EquipWearReq)
	if !ok {
		return config.PROTO_ERROR
	}

	equip := user.GetEquip4Key(req.EquipKey)
	if equip == nil {
		logger.Error("equip not exist, equipKey: %v, uid: %v", req.EquipKey, user.GetUid())
		return SendMsg(config.SC_EquipWearRsp, &pb.SC_EquipWearRsp{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
	}
	role := user.GetRoleById(req.RoleId)
	if role == nil {
		logger.Error("role not exist, roleId: %v, uid: %v", req.RoleId, user.GetUid())
		return SendMsg(config.SC_EquipWearRsp, &pb.SC_EquipWearRsp{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
	}
	ret := EquipWear(equip, role, req.IsWear, user)
	if ret != config.OK {
		logger.Error("equip wear fail, equip: %v, uid: %v", equip, user.GetUid())
		return SendMsg(config.SC_EquipWearRsp, &pb.SC_EquipWearRsp{RetCode: int32(ret)}, buf, user)
	}

	return SendMsg(config.SC_EquipWearRsp, &pb.SC_EquipWearRsp{RetCode: config.OK, Equip: sharemem.PacketEquip(equip, user), Role: user.PacketUserRole(role)}, buf, user)
}

func EquipJewelWearReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_EquipJewelWearReq, new(pb.CS_EquipJewelWearReq), buf, user).(*pb.CS_EquipJewelWearReq)
	if !ok {
		return config.PROTO_ERROR
	}

	equip := user.GetEquip4Key(req.EquipKey)
	if equip == nil {
		logger.Error("equip not exist, equipKey: %v, uid: %v", req.EquipKey, user.GetUid())
		return SendMsg(config.SC_EquipJewelWearRsp, &pb.SC_EquipJewelWearRsp{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
	}
	if req.Jewel == nil {
		logger.Error("equip jewel not exist, uid: %v", user.GetUid())
		return SendMsg(config.SC_EquipJewelWearRsp, &pb.SC_EquipJewelWearRsp{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
	}
	jewel := user.GetEquipJewel4Key(req.Jewel.EquipJewelKey)
	if jewel == nil {
		logger.Error("equip jewel not exist, equipJewelKey: %v, uid: %v", req.Jewel.EquipJewelKey, user.GetUid())
		return SendMsg(config.SC_EquipJewelWearRsp, &pb.SC_EquipJewelWearRsp{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
	}
	ret := EquipJewelWear(equip, req.JewelIndex, jewel, req.IsWear, user)
	if ret != config.OK {
		logger.Error("equip jewel wear fail, equip: %v, uid: %v", equip, user.GetUid())
		return SendMsg(config.SC_EquipJewelWearRsp, &pb.SC_EquipJewelWearRsp{RetCode: int32(ret)}, buf, user)
	}

	pbCurrJewel := new(pb.EquipJewel)
	if equip.JewelList[req.JewelIndex] != 0 {
		currJewel := user.GetEquipJewel4Key(equip.JewelList[req.JewelIndex])
		if currJewel == nil {
			logger.Error("get currJewel is nil, equipJewelKey: %v", equip.JewelList[req.JewelIndex])
			return SendMsg(config.SC_EquipJewelWearRsp, &pb.SC_EquipJewelWearRsp{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
		}
		pbCurrJewel = sharemem.PacketEquipJewel(currJewel)
	}
	var pbRole *pb.User_Role = nil
	if equip.RoleId != 0 {
		role := user.GetRoleById(equip.RoleId)
		if role == nil {
			logger.Error("role not exist, roleId: %v, uid: %v", equip.RoleId, user.GetUid())
			return SendMsg(config.SC_EquipJewelWearRsp, &pb.SC_EquipJewelWearRsp{RetCode: config.OBJECT_NOT_FOUND}, buf, user)
		}
		pbRole = user.PacketUserRole(role)
	}
	return SendMsg(config.SC_EquipJewelWearRsp, &pb.SC_EquipJewelWearRsp{RetCode: config.OK, Jewel: pbCurrJewel, Equip: sharemem.PacketEquip(equip, user), Role: pbRole}, buf, user)
}

func EquipComposeReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_EquipComposeReq, new(pb.CS_EquipComposeReq), buf, user).(*pb.CS_EquipComposeReq)
	if !ok {
		return config.PROTO_ERROR
	}

	var retData = new(pb.SC_EquipComposeRsp)
	retData.RetCode = config.OK
	retData.IsWeapon = req.IsWeapon
	ok = ComposeItem(req.EquipItemId, user)
	if !ok {
		retData.RetCode = config.SERVER_ERROR
		return SendMsg(config.SC_EquipComposeRsp, retData, buf, user)
	}
	if req.IsWeapon {
		if user.GetLastComposeWeaponKey() == 0 {
			retData.RetCode = config.SERVER_ERROR
			return SendMsg(config.SC_EquipComposeRsp, retData, buf, user)
		}
		retData.Weapon = user.PacketWeapon(user.GetWeaponByKey(user.GetLastComposeWeaponKey()))
		user.TriggerActivityTask(gdconf.ActivityTaskFinishCondWeaponCompose, 1)
	} else {
		if user.GetLastComposeEquip() == nil {
			retData.RetCode = config.SERVER_ERROR
			return SendMsg(config.SC_EquipComposeRsp, retData, buf, user)
		}
		retData.Equip = sharemem.PacketEquip(user.GetLastComposeEquip(), user)
		var equipConfig = gdconf.GetEquipConfig(retData.Equip.GetItemId())
		if equipConfig != nil {
			TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_BUILD_EQUIP_FOR_GROUP, true, equipConfig.Group, 1)
		}
		user.TriggerActivityTask(gdconf.ActivityTaskFinishCondEquipCompose, 1)
	}
	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_BUILD_EQUIP, true, 1)
	return SendMsg(config.SC_EquipComposeRsp, retData, buf, user)
}

// AddEquip 添加装备对象
func AddEquip(equipId int32, user *sharemem.User) bool {
	for cell := 0; cell < len(user.Equip); cell++ {
		equip := &(user.Equip[cell])
		if equip.IsUse() {
			continue
		}
		equip.MemInit()
		equip.Id.NewVal = equipId
		equip.Cell = int32(cell)
		ok := CreateEquip(equip, equipId, user)
		if !ok {
			logger.Error("create equip fail, uid: %v", user.GetUid())
			return false
		}
		// 添加索引
		user.Add2EquipMap(sharemem.BuildEquipKey(equipId, int32(cell)), equip)
		SendMsg(config.SC_EquipUpdateNtf, &pb.SC_EquipUpdateNtf{Equip: sharemem.PacketEquip(equip, user)}, nil, user)
		user.SetLastComposeEquip(equip)
		return true
	}
	logger.Error("no empty equip found, uid: %v", user.GetUid())
	return false
}

// CostEquip 删除装备对象
func CostEquip(equip *sharemem.Equip, user *sharemem.User) (int32, bool) {
	if equip.RoleId != 0 {
		logger.Error("equip already be wear, equipId: %v, roleId: %v, uid: %v", equip.GetId(), equip.RoleId, user.GetUid())
		return 0, false
	}
	for _, equipJewelKey := range equip.JewelList {
		if equipJewelKey == 0 {
			continue
		}
		jewel := user.GetEquipJewel4Key(equipJewelKey)
		if jewel == nil {
			logger.Error("get jewel is nil, equipJewelKey: %v, uid: %v", equipJewelKey, user.GetUid())
			continue
		}
		jewel.EquipKey = 0
		SendMsg(config.SC_EquipJewelUpdateNtf, &pb.SC_EquipJewelUpdateNtf{Jewel: sharemem.PacketEquipJewel(jewel)}, nil, user)
	}
	equipKey := sharemem.BuildEquipKey(equip.GetId(), equip.Cell)
	user.RemoveEquip(equipKey, equip.Cell)
	return equipKey, true
}

// CreateEquip 初始化装备对象
func CreateEquip(equip *sharemem.Equip, equipId int32, user *sharemem.User) bool {
	logger.Debug("create equip, equipId: %v, uid: %v", equipId, user.GetUid())
	equipConfig := gdconf.GetEquipConfig(equipId)
	if equipConfig == nil {
		logger.Error("get equipConfig is nil, equipId: %v, uid: %v", equipId, user.GetUid())
		return false
	}
	equip.Level = 0
	equip.Exp = 0

	// 等级组随机
	levelGroup := EquipLevelGroupRandom(equipConfig)
	if levelGroup == -1 {
		logger.Error("equip level group random error, uid: %v", user.GetUid())
		return false
	}
	equip.LevelGroup = levelGroup

	// if equipConfig.InitAffixNum > equipConfig.MaxAffixNum || equipConfig.InitAffixNum > EQUIP_AFFIX_LIST_MAX {
	// 	logger.Error("equip init affix num error, equipId: %v, uid: %v", equipId, u.GetUid())
	// 	return false
	// }
	//
	// for i := 0; i < int(equipConfig.InitAffixNum); i++ {
	// 	ok := u.EquipAffixAppend(&(equip.AffixList), equipConfig, nil)
	// 	if !ok {
	// 		return false
	// 	}
	// }

	logger.Debug("create equip ok, equip: %v, uid: %v", equip, user.GetUid())
	return true
}

func EquipLevelGroupRandom(equipConfig *gdconf.EquipConfig) int32 {
	weightAll := int32(0)
	for _, levelGroupWeight := range equipConfig.LevelGroupWeight {
		weightAll += levelGroupWeight[1]
	}
	randNum := random.GetRandomInt32(0, weightAll-1)
	sumWeight := int32(0)
	for _, levelGroupWeight := range equipConfig.LevelGroupWeight {
		sumWeight += levelGroupWeight[1]
		if sumWeight > randNum {
			return levelGroupWeight[0]
		}
	}
	return -1
}

// EquipUpgrade 装备升级
func EquipUpgrade(equip *sharemem.Equip, req *pb.CS_EquipUpgradeReq, user *sharemem.User) int16 {
	logger.Debug("equip upgrade, equipId: %v, uid: %v", equip.GetId(), user.GetUid())
	// 检查配置
	equipConfig := gdconf.GetEquipConfig(equip.GetId())
	if equipConfig == nil {
		logger.Error("get equipConfig is nil, equipId: %v, uid: %v", equip.GetId(), user.GetUid())
		return config.CONFIG_NOT_FOUND
	}
	equipLevelConfig := gdconf.GetConfigEquipLevelByGroupAndLevel(equip.LevelGroup, int32(equip.Level))
	if equipLevelConfig == nil {
		logger.Error("get equipLevelConfig is nil, group: %v, level: %v, uid: %v", equip.LevelGroup, equip.Level, user.GetUid())
		return config.CONFIG_NOT_FOUND
	}
	goldExpRatio := gdconf.GetConstFloat("EQUIPUPGRADECOST")
	equipConvExpRatio := gdconf.GetConstFloat("EQUIPEXP")
	skillAppendLevel := make([]int16, 0)
	for _, levelStr := range strings.Split(gdconf.GetConstStr("ORDINARYSKILLUNLOCK"), "|") {
		level, err := strconv.Atoi(levelStr)
		if err != nil {
			return config.CONFIG_NOT_FOUND
		}
		skillAppendLevel = append(skillAppendLevel, int16(level))
	}
	// 是否达到最大等级
	if equipLevelConfig.Exp == 0 {
		logger.Error("equip max level limit, equipId: %v, uid: %v", equip.GetId(), user.GetUid())
		return config.SERVER_ERROR
	}
	// 检查道具
	if req.ItemList != nil {
		ret := CheckSubItems(req.ItemList, user)
		if ret != config.OK {
			logger.Error("use item error code: %v, itemList: %v, uid: %v", ret, req.ItemList, user.GetUid())
			return int16(ret)
		}
	}
	// 检查装备
	foodEquipList := make([]*sharemem.Equip, 0)
	for _, foodEquipKey := range req.FoodEquipList {
		foodEquip := user.GetEquip4Key(foodEquipKey)
		if foodEquip == nil {
			logger.Error("food equip not exist, foodEquipKey: %v, uid: %v", foodEquipKey, user.GetUid())
			return config.OBJECT_NOT_FOUND
		}
		if foodEquip.Cell == equip.Cell {
			logger.Error("equip can not eat self, foodEquipKey: %v, uid: %v", foodEquipKey, user.GetUid())
			return config.SERVER_ERROR
		}
		if foodEquip.RoleId != 0 {
			logger.Error("equip already be wear, foodEquipKey: %v, roleId: %v, uid: %v", foodEquipKey, foodEquip.RoleId, user.GetUid())
			return config.SERVER_ERROR
		}
		foodEquipList = append(foodEquipList, foodEquip)
	}
	// 计算道具的总经验
	totalAddExp := int32(0)
	for _, item := range req.ItemList {
		itemActiveConfig := gdconf.GetItemUseConfig(item.Id)
		if itemActiveConfig == nil {
			return config.CONFIG_NOT_FOUND
		}
		if itemActiveConfig.Param[0] != gdconf.ItemUseTypeAddGlobalExp {
			logger.Error("item type is not exp, type: %v, uid: %v", itemActiveConfig.Param[0], user.GetUid())
			return config.SERVER_ERROR
		}
		totalAddExp += itemActiveConfig.Param[1] * item.Num
	}
	// 计算食物装备的总经验
	for _, foodEquip := range foodEquipList {
		foodEquipConfig := gdconf.GetEquipConfig(foodEquip.GetId())
		if foodEquipConfig == nil {
			logger.Error("get foodEquipConfig is nil, equipId: %v, uid: %v", foodEquip.GetId(), user.GetUid())
			return config.CONFIG_NOT_FOUND
		}
		totalAddExp += foodEquipConfig.BaseConvExp
		for level := int16(1); level < foodEquip.Level; level++ {
			foodEquipLevelConfig := gdconf.GetConfigEquipLevelByGroupAndLevel(foodEquip.LevelGroup, int32(level))
			if foodEquipLevelConfig == nil {
				logger.Error("get foodEquipLevelConfig is nil, levelGroup: %v, level: %v", foodEquip.LevelGroup, level)
				return config.CONFIG_NOT_FOUND
			}
			totalAddExp += int32(float64(foodEquipLevelConfig.Exp) * equipConvExpRatio)
		}
		totalAddExp += int32(float64(foodEquip.Exp) * equipConvExpRatio)
	}
	// 装备增加经验
	oldLevel := equip.Level
	newExp := equip.Exp
	newLevel := equip.Level
	newExp += totalAddExp
	var remainExp int32 = 0
	// 装备升级
	for i := 0; i < 1000; i++ {
		// 获取装备当前等级配置表
		equipLevelConfig = gdconf.GetConfigEquipLevelByGroupAndLevel(equip.LevelGroup, int32(newLevel))
		if equipLevelConfig == nil {
			break
		}
		if equipLevelConfig.Exp == 0 {
			remainExp = newExp
			newExp = 0
			break
		}
		// 装备经验小于升级所需的经验则跳出循环
		if newExp < equipLevelConfig.Exp {
			break
		}
		// 装备等级提升
		newExp -= equipLevelConfig.Exp
		newLevel++
		user.TriggerActivityTask(gdconf.ActivityTaskFinishCondEquipUpgrade)
	}
	// 扣除道具
	SubItems(req.ItemList, user)
	ok := CostItems(map[int32]int32{gdconf.ITEM_GOLD: int32(float32(goldExpRatio) * float32(math.Max(float64(totalAddExp-remainExp), 0)))}, user)
	if !ok {
		return config.ITEM_NOT_ENOUGH
	}
	// 扣除装备
	deleteEquipKeyList := make([]int32, 0)
	for _, foodEquip := range foodEquipList {
		equipKey, ok := CostEquip(foodEquip, user)
		if !ok {
			logger.Error("cost equip error, equipId: %v, uid: %v", foodEquip.GetId(), user.GetUid())
			continue
		}
		deleteEquipKeyList = append(deleteEquipKeyList, equipKey)
	}
	SendMsg(config.SC_EquipDeleteNtf, &pb.SC_EquipDeleteNtf{DeleteEquipKeyList: deleteEquipKeyList}, nil, user)
	// 升到指定等级追加词条
	for level := oldLevel + 1; level <= newLevel; level++ {
		if slices.Contains[[]int16, int16](skillAppendLevel, level) {
			// ok := u.EquipAffixAppend(&(equip.AffixList), equipConfig, nil)
			// if !ok {
			// 	logger.Error("equip affix append fail, equipId: %v, uid: %v", equip.GetId(), u.GetUid())
			// }
			ok := equip.EquipSkillAppend(level)
			if !ok {
				logger.Error("equip skill append fail, equipId: %v, uid: %v", equip.GetId(), user.GetUid())
			}
		}
	}
	var oldValue = equip.Level
	// 修改数据
	equip.Level = newLevel
	equip.Exp = newExp
	equip.SetSync()
	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_EQUIP_UPGRADE, true)
	if oldValue != equip.Level {
		TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_EQUIP_COUNT_BY_LEVEL, true)
	}
	logger.Debug("equip upgrade ok, equip: %v, uid: %v", equip, user.GetUid())
	return config.OK
}

// EquipWear 装备穿戴
func EquipWear(equip *sharemem.Equip, role *sharemem.Role, isWear bool, user *sharemem.User) int16 {
	equipConfig := gdconf.GetEquipConfig(equip.GetId())
	if equipConfig == nil {
		logger.Error("get equipConfig is nil, equipId: %v", equip.GetId())
		return config.CONFIG_NOT_FOUND
	}
	equipPos := equipConfig.WeaponPos - 1
	if equipPos < 0 || equipPos > 6 {
		logger.Error("equip pos invalid, equipId: %v, pos: %v", equip.GetId(), equipConfig.WeaponPos)
		return config.SERVER_ERROR
	}
	if isWear {
		// 穿戴
		if equip.RoleId != 0 {
			// 该装备当前有其他角色穿戴
			oldRole := user.GetRoleById(equip.RoleId)
			if oldRole == nil {
				logger.Error("get oldRole is nil, roleId: %v, uid: %v", equip.RoleId, user.GetUid())
				return config.OBJECT_NOT_FOUND
			}
			oldRole.EquipList[equipPos] = 0
			oldRole.SetSync()
			equip.RoleId = 0
			SendMsg(config.SC_RoleUpdateNtf, &pb.SC_RoleUpdateNtf{Role: user.PacketUserRole(oldRole)}, nil, user)
		}
		if role.EquipList[equipPos] != 0 {
			// 该角色该部位当前有穿戴其他装备
			oldEquip := user.GetEquip4Key(role.EquipList[equipPos])
			if oldEquip == nil {
				logger.Error("get oldEquip is nil, equipId: %v", oldEquip.GetId())
				return config.OBJECT_NOT_FOUND
			}
			oldEquip.RoleId = 0
			oldEquip.SetSync()
			SendMsg(config.SC_EquipUpdateNtf, &pb.SC_EquipUpdateNtf{Equip: sharemem.PacketEquip(oldEquip, user)}, nil, user)
		}
		role.EquipList[equipPos] = sharemem.BuildEquipKey(equip.GetId(), equip.Cell)
		equip.RoleId = role.GetId()
	} else {
		// 脱下
		if equip.RoleId == 0 {
			logger.Error("equip not be wear, equipId: %v, uid: %v", equip.GetId(), user.GetUid())
			return config.SERVER_ERROR
		}
		role.EquipList[equipPos] = 0
		equip.RoleId = 0
	}
	equip.SetSync()
	role.SetSync()
	SendMsg(config.SC_RoleUpdateNtf, &pb.SC_RoleUpdateNtf{Role: user.PacketUserRole(role)}, nil, user)
	SendMsg(config.SC_EquipUpdateNtf, &pb.SC_EquipUpdateNtf{Equip: sharemem.PacketEquip(equip, user)}, nil, user)
	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_EQUIP_WEAR, true)
	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_ROLE_WEAR_EQUIP_COUNT, true)
	return config.OK
}

// EquipJewelWear 装备宝石镶嵌
func EquipJewelWear(equip *sharemem.Equip, jewelIndex int32, jewel *sharemem.EquipJewel, isWear bool, user *sharemem.User) int16 {
	logger.Debug("equip jewel wear, equipId: %v, jewelIndex: %v, jewel: %v, isWear: %v, uid: %v", equip.GetId(), jewelIndex, jewel, isWear, user.GetUid())
	equipConfig := gdconf.GetEquipConfig(equip.GetId())
	if equipConfig == nil {
		logger.Error("get equipConfig is nil, equipId: %v, uid: %v", equip.GetId(), user.GetUid())
		return config.CONFIG_NOT_FOUND
	}
	equipJewelConfig := gdconf.GetEquipJewelConfig(jewel.GetId())
	if equipJewelConfig == nil {
		logger.Error("get equipJewelConfig is nil, jewelId: %v, uid: %v", jewel.GetId(), user.GetUid())
		return config.CONFIG_NOT_FOUND
	}
	if int(jewelIndex) >= int(equipConfig.JewelNum) {
		logger.Error("client req jewel index error, jewelIndex: %v, uid: %v", jewelIndex, user.GetUid())
		return config.SERVER_ERROR
	}
	if isWear {
		// 镶嵌
		if jewel.EquipKey != 0 {
			// 该宝石当前有其他装备镶嵌
			oldEquip := user.GetEquip4Key(jewel.EquipKey)
			if oldEquip == nil {
				logger.Error("get oldEquip is nil, equipKey: %v, uid: %v", jewel.EquipKey, user.GetUid())
				return config.OBJECT_NOT_FOUND
			}
			oldEquip.JewelList[jewelIndex] = 0
			oldEquip.SetSync()
			jewel.EquipKey = 0
			if oldEquip.RoleId != 0 {
				oldRole := user.GetRoleById(oldEquip.RoleId)
				if oldRole == nil {
					logger.Error("role not exist, roleId: %v, uid: %v", oldEquip.RoleId, user.GetUid())
					return config.OBJECT_NOT_FOUND
				}
				SendMsg(config.SC_RoleUpdateNtf, &pb.SC_RoleUpdateNtf{Role: user.PacketUserRole(oldRole)}, nil, user)
			}
			SendMsg(config.SC_EquipUpdateNtf, &pb.SC_EquipUpdateNtf{Equip: sharemem.PacketEquip(oldEquip, user)}, nil, user)
		}
		if equip.JewelList[jewelIndex] != 0 {
			// 该装备该孔位当前有镶嵌其他宝石
			oldJewel := user.GetEquipJewel4Key(equip.JewelList[jewelIndex])
			if oldJewel == nil {
				logger.Error("get oldJewel is nil, equipJewelKey: %v", equip.JewelList[jewelIndex])
				return config.OBJECT_NOT_FOUND
			}
			oldJewel.EquipKey = 0
			oldJewel.SetSync()
			SendMsg(config.SC_EquipJewelUpdateNtf, &pb.SC_EquipJewelUpdateNtf{Jewel: sharemem.PacketEquipJewel(oldJewel)}, nil, user)
		}
		jewel.EquipKey = sharemem.BuildEquipKey(equip.GetId(), equip.Cell)
		equip.JewelList[jewelIndex] = sharemem.BuildEquipJewelKey(jewel.GetId(), jewel.Cell)
	} else {
		// 摘除
		if equip.JewelList[jewelIndex] == 0 {
			logger.Error("jewel not be wear, equipId: %v, uid: %v", equip.GetId(), user.GetUid())
			return config.SERVER_ERROR
		}
		jewel.EquipKey = 0
		equip.JewelList[jewelIndex] = 0
	}
	equip.SetSync()
	jewel.SetSync()
	if equip.RoleId != 0 {
		role := user.GetRoleById(equip.RoleId)
		if role == nil {
			logger.Error("role not exist, roleId: %v, uid: %v", equip.RoleId, user.GetUid())
			return config.OBJECT_NOT_FOUND
		}
		SendMsg(config.SC_RoleUpdateNtf, &pb.SC_RoleUpdateNtf{Role: user.PacketUserRole(role)}, nil, user)
	}
	SendMsg(config.SC_EquipUpdateNtf, &pb.SC_EquipUpdateNtf{Equip: sharemem.PacketEquip(equip, user)}, nil, user)
	SendMsg(config.SC_EquipJewelUpdateNtf, &pb.SC_EquipJewelUpdateNtf{Jewel: sharemem.PacketEquipJewel(jewel)}, nil, user)
	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_EQUIP_JEWEL_WEAR, true)
	logger.Debug("equip jewel wear ok, jewelList: %v, uid: %v", equip.JewelList, user.GetUid())
	return config.OK
}

func AddEquipJewel(jewelId int32, user *sharemem.User) bool {
	for cell := 0; cell < len(user.EquipJewel); cell++ {
		jewel := &(user.EquipJewel[cell])
		if jewel.IsUse() {
			continue
		}
		jewel.Id.NewVal = jewelId
		jewel.Cell = int32(cell)
		// 添加索引
		user.Add2EquipJewelMap(sharemem.BuildEquipJewelKey(jewelId, int32(cell)), jewel)
		SendMsg(config.SC_EquipJewelUpdateNtf, &pb.SC_EquipJewelUpdateNtf{Jewel: sharemem.PacketEquipJewel(jewel)}, nil, user)
		return true
	}
	logger.Error("no empty equip jewel found, uid: %v", user.GetUid())
	return false
}

func CostEquipJewel(equipJewel *sharemem.EquipJewel, user *sharemem.User) (int32, bool) {
	if equipJewel.EquipKey != 0 {
		logger.Error("equip jewel already be wear, jewelId: %v, equipKey: %v, uid: %v", equipJewel.GetId(), equipJewel.EquipKey, user.GetUid())
		return 0, false
	}
	equipJewelKey := sharemem.BuildEquipJewelKey(equipJewel.GetId(), equipJewel.Cell)
	user.RemoveEquipJewel(equipJewelKey, equipJewel.Cell)
	return equipJewelKey, true
}
